package juc.concurrent;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/*
 * ConcurrentHashMap 防止线程安全问题
 * */
public class Test1 {
    public static void main(String[] args) {
        generateWordFile();
//        test();
        demo(() -> new ConcurrentHashMap<String, LongAdder>(), (map, words) -> {
            for (String word : words) {
               /* synchronized (map) {
                    Integer count = map.get(word);
                    map.put(word, count != null ? count + 1 : 1);
                }*/
                //原子的
                LongAdder longAdder = map.computeIfAbsent(word, (key) -> new LongAdder());
                //原子的 两者不存在逻辑联系所以整个就是原子的
                longAdder.increment();
            }
        });
    }

    public static void test() {

    }

    public static <V> void demo(Supplier<Map<String, V>> supplier, BiConsumer<Map<String, V>, List<String>> biConsumer) {
        //多线程读取文件中的单词 统计各单词出现次数
        Map<String, V> map = supplier.get();
        CountDownLatch countDownLatch = new CountDownLatch(26);
        for (int i = 0; i < 26; i++) {
            int f=i;
            new Thread(() -> {
                List<String> words = new ArrayList<>(100);
                try (BufferedReader bufferedReader = new BufferedReader(new FileReader((f + 1) + ".txt"))) {
                    String temp = "";
                    while ((temp = bufferedReader.readLine()) != null) {
                        words.add(temp);
                    }
                    biConsumer.accept(map, words);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            }).start();

        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(map);
    }

    public static void generateWordFile() {
        String[] words = new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
        Random random = new Random();
        BufferedOutputStream[] bufferedOutputStreams = new BufferedOutputStream[26];
        for (int i = 0; i < 26; i++) {
            try {
                FileOutputStream fileOutputStream = new FileOutputStream((i + 1) + ".txt");
                BufferedOutputStream stream = new BufferedOutputStream(fileOutputStream);
                bufferedOutputStreams[i] = stream;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        for (int i = 0; i < 200; i++) {
            for (int j = 0; j < 26; j++) {
                String temp = words[j] + "\n";
                int f = random.nextInt(26);
                BufferedOutputStream bufferedOutputStream = bufferedOutputStreams[f];
                try {
                    bufferedOutputStream.write(temp.getBytes(StandardCharsets.UTF_8));

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        for (int i = 0; i < 26; i++) {
            BufferedOutputStream bufferedOutputStream = bufferedOutputStreams[i];
            try {
                bufferedOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
